package panel.role.texturejsonedit;

import com.alibaba.fastjson2.JSON;
import com.plealog.genericapp.api.EZEnvironment;
import model.MaterialJson;
import model.TexturesJson;
import net.miginfocom.swing.MigLayout;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.JXTextField;
import session.BaseSession;
import session.RoleSession;
import util.MaterialDataUtil;
import util.TetureJsonComboBox;

import javax.swing.*;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.event.TableModelEvent;
import javax.swing.filechooser.FileFilter;
import javax.swing.table.DefaultTableModel;
import java.awt.event.ItemEvent;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 材质JSON数据编辑
 */
public class MapPathConfigurePanel extends JPanel {
	private JButton okButton = new JButton("确定修改");
	private JTextField ddsFileField = new JXTextField("dds文件路径");
	private JButton ddsFileButton = new JButton("选择");
	private JTextField materialFileField = new JXTextField("material文件路径");
	private JButton materialFileButton = new JButton("选择");
	private JFileChooser fileChooser = new JFileChooser();
	private TetureJsonComboBox comboBox = new TetureJsonComboBox(new Vector<>(RoleSession.TEXTURE_JSON_ITEMS.keySet()));
	private JXTable table;
	private DefaultTableModel tableModel;

	public MapPathConfigurePanel() {
		setLayout(new MigLayout("wrap 2", "grow"));

		initLayout();
		initListener();
	}

	private void initLayout() {
		JLabel materialPathLabel = new JLabel("Mtd path");
		JLabel ddsLabel = new JLabel("dds文件目录");
		JLabel materialFileLabel = new JLabel("材质文件");

		ddsFileField.setColumns(30);
		ddsFileField.setText(RoleSession.DDS_PATH);
		materialFileField.setColumns(30);
		materialFileField.setText(RoleSession.MATERIAL_PATH);

		tableModel = new DefaultTableModel();
		table = new JXTable(tableModel);
		table.setSortable(false);
		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		// 默认第一个材质
		switchMaterial((String) comboBox.getSelectedItem());
		comboBox.addItemListener(e -> {
			if (e.getStateChange() == ItemEvent.SELECTED) {
				switchMaterial((String) comboBox.getSelectedItem());
			}
		});

		add(ddsLabel, "span, split 3");
		add(ddsFileField);
		add(ddsFileButton);
		add(materialFileLabel, "span, split 3");
		add(materialFileField);
		add(materialFileButton);
		add(materialPathLabel, "split 2, span");
		add(comboBox);
		JScrollPane scrollPane = new JScrollPane(table);
		scrollPane.setBorder(null);
		add(scrollPane, "span, center,growx");
		add(okButton, "span, center");
	}

	public static Vector<String> TABLE_COL = new Vector<>();

	static {
		TABLE_COL.add("Type");
		TABLE_COL.add("贴图后缀");
	}

	private String currentKey;

	/**
	 * 更改表格模型数据
	 *
	 * @param key 材质名
	 */
	private void switchMaterial(String key) {
		if (Objects.equals(currentKey, key)) return;
		currentKey = key;
		List<String[]> items = RoleSession.TEXTURE_JSON_ITEMS.get(key);

		Vector<Vector<String>> data = new Vector<>();
		for (String[] item : items) {
			Vector<String> row = new Vector<>();
			row.add(item[0]);
			row.add(item[1]);
			data.add(row);
		}

		tableModel.setDataVector(data, TABLE_COL);
	}

	private void initListener() {
		tableModel.addTableModelListener(e -> {
			if (e.getType() == TableModelEvent.UPDATE && e.getFirstRow() != -1) {
				List<String[]> list = RoleSession.TEXTURE_JSON_ITEMS.get(currentKey);
				String[] item = list.get(e.getFirstRow());
				if (e.getColumn() == 0)
					item[0] = (String) tableModel.getValueAt(e.getFirstRow(), e.getColumn());
				else
					item[1] = (String) tableModel.getValueAt(e.getFirstRow(), e.getColumn());
			}
		});
		addAncestorListener(new AncestorListener() {
			@Override
			public void ancestorAdded(AncestorEvent event) {
				ddsFileField.setText(RoleSession.DDS_PATH);
				materialFileField.setText(RoleSession.MATERIAL_PATH);

			}

			@Override
			public void ancestorRemoved(AncestorEvent event) {
				BaseSession.setVal(RoleSession.class, "DDS_PATH", ddsFileField.getText());
				BaseSession.setVal(RoleSession.class, "MATERIAL_PATH", materialFileField.getText());
			}

			@Override
			public void ancestorMoved(AncestorEvent event) {

			}
		});

		fileChooser.setCurrentDirectory(new File("."));
		ddsFileButton.addActionListener(e -> {
			fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
			fileChooser.setFileFilter(null);
			if (fileChooser.showOpenDialog(EZEnvironment.getParentFrame()) == JFileChooser.APPROVE_OPTION) {
				String newVal = fileChooser.getSelectedFile().getAbsolutePath();
				ddsFileField.setText(newVal);
				BaseSession.setVal(RoleSession.class, "DDS_PATH", newVal);
			}
		});
		materialFileButton.addActionListener(e -> {
			fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
			fileChooser.setFileFilter(new FileFilter() {
				@Override
				public boolean accept(File f) {
					return f.getName().endsWith(".json");
				}

				@Override
				public String getDescription() {
					return null;
				}
			});
			if (fileChooser.showOpenDialog(EZEnvironment.getParentFrame()) == JFileChooser.APPROVE_OPTION) {
				String newVal = fileChooser.getSelectedFile().getAbsolutePath();
				materialFileField.setText(newVal);
				BaseSession.setVal(RoleSession.class, "MATERIAL_PATH", newVal);
			}
		});

		okButton.addActionListener(e -> {
			String msg = checkData();
			if (msg != null) {
				JOptionPane.showConfirmDialog(EZEnvironment.getParentFrame(), msg, "提示", JOptionPane.DEFAULT_OPTION);
				return;
			}

			// 为了省事，这里使用单线程
			processTask();
		});
	}

	private String checkData() {
		if (!new File(ddsFileField.getText()).isDirectory()) return "dds文件路径不存在";
		if (!new File(materialFileField.getText()).isFile()) return "Material文件不存在";
		return null;
	}

	private void processTask() {
		// 解析
		File file = new File(materialFileField.getText());
		List<MaterialJson> materialJsons = MaterialDataUtil.parseMaterialFile(file);

		// 修改
		String[] filenames = new File(ddsFileField.getText()).list((dir, name) -> name.endsWith(".dds"));
		if (filenames == null || filenames.length == 0) {
			JOptionPane.showConfirmDialog(EZEnvironment.getParentFrame(), "指定目录下没有找到dds文件", "提示", JOptionPane.DEFAULT_OPTION);
			return;
		}
		//<文件后缀集, 文件名>
		Map<HashSet<String>, String> ddsFiles = Arrays.stream(filenames)
				.map(s1 -> s1.substring(0, s1.length() - 4))
				.collect(Collectors.toMap(s12 -> {
					HashSet<String> set = new HashSet<>(List.of(s12.split("_")));
					set.remove(""); // 空串不要
					return set;
				}, s13 -> s13 + ".tif"));


		Map<String, List<String[]>> textureJsonItems = RoleSession.TEXTURE_JSON_ITEMS;

		for (MaterialJson materialJson : materialJsons) {
			int index = materialJson.getName().indexOf(".fbx_");
			if (index == -1) continue; //前面两个是不符合的，不进行修改

			String materialName = materialJson.getName().substring(index + 5);

			List<String[]> jsonItems = textureJsonItems.get(materialJson.getMTD());
			if (jsonItems == null) continue; // 没有给该材质自定义

			// 只是匹配type并填入path，舍弃，决定采用填入所有type
			// HashMap<String, String> typeSuffixMap = new HashMap<>();
			// jsonItems.forEach(textureJsonItem -> {
			// 	if (!textureJsonItem.getType().equals(""))
			// 		typeSuffixMap.put(textureJsonItem.getType(), textureJsonItem.getSuffix());
			// });

			// for (TexturesJson texture : materialJson.getTextures()) {
			// 	String suffix = typeSuffixMap.get(texture.getType());
			// 	if (suffix == null) {
			// 		texture.setPath("");
			// 		continue; //找不到表示没有为该type设置dds文件后缀
			// 	}
			//
			// 	boolean flag = false;
			// 	for (HashSet<String> set : ddsFiles.keySet()) {
			// 		if (set.contains(suffix) && set.contains(materialName)) { //这里前缀后缀都行
			// 			// 这张图片符合前/后缀
			// 			texture.setPath(ddsFiles.get(set));
			// 			flag = true;
			// 			break; //只取第一张
			// 		}
			// 	}
			// 	if (!flag) {
			// 		// 没有图片就置空
			// 		texture.setPath("");
			// 	}
			// }

			List<TexturesJson> textures = materialJson.getTextures();
			for (int i = 0, len = textures.size(); i < len; i++) {
				// 这里可能会导致数组越界，因此留空要大，暂时留空20个
				String[] item = jsonItems.get(i);
				TexturesJson texture = textures.get(i);
				texture.setType(item[0]);
				if (item[0].equals("") || item[1].equals("")) {
					texture.setPath("");
					continue;
				}

				// 匹配后缀
				HashSet<String> suffixSet = new HashSet<>(List.of(item[1].split(",")));
				suffixSet.remove("");
				boolean flag = false;
				for (HashSet<String> set : ddsFiles.keySet()) {
					HashSet<String> tmpSet = new HashSet<>(suffixSet);
					tmpSet.retainAll(set);
					//这里前缀后缀都行，并且需要考虑materialName中也有下划线的情况
					if (tmpSet.size() != 0 && Arrays.stream(materialName.split("_")).allMatch(set::contains)) {
						// 这张图片符合前/后缀
						texture.setPath(ddsFiles.get(set));
						flag = true;
						break; //只取第一张
					}
				}
				if (!flag) {
					// 没有图片就置空
					texture.setPath("");
				}
			}
		}

		// 写出
		try (BufferedWriter bw = new BufferedWriter(new FileWriter(file, StandardCharsets.UTF_8))) {
			bw.write(JSON.toJSONString(materialJsons));
		} catch (IOException e) {
			JOptionPane.showConfirmDialog(EZEnvironment.getParentFrame(),
					"文件写出失败，原因为：" + e.getMessage(), "提示", JOptionPane.DEFAULT_OPTION);
		}

		JOptionPane.showConfirmDialog(EZEnvironment.getParentFrame(), file.getName() + "文件修改成功！", "提示", JOptionPane.DEFAULT_OPTION);
	}
}
